/**
 * JAVACC DEMO 1.0
 */
package com.apache.ius.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.apache.api.manager.PluginConnector;
import com.apache.api.vo.ParamsVo;
import com.apache.api.vo.ResultEntity;
import com.apache.cache.util.Validator;
import com.apache.database.constant.SpringContextLoader;
import com.apache.database.db.IDao;
import com.apache.database.model.MethodParam;
import com.apache.exception.BusinessException;
import com.apache.ius.CustomMethodFactory;
import com.apache.ius.FelToolsUtil;
import com.apache.ius.IusSqlTools;
import com.apache.ius.plugin.CustomMethodPlugin;
import com.apache.ius.plugin.IusSqlPorxyPlugin;
import com.apache.ius.plugin.MaxContentPorxyPlugin;
import com.apache.tools.StrUtil;

import net.sf.json.JSONObject;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

/**
 * description:  IUS事务处理插件
 *
 * @author Administrator 创建时间：2016-12-7
 */
public class PlateTransactionPluginImpl implements PluginConnector {
	private Logger log = Logger.getLogger(getClass());
	private IDao iusPubDao;

	private IusSqlPorxyPlugin iusSqlPorxyPlugin;

	@Autowired
	@Qualifier("iusCachePlugin")
	private CachePluginImpl iusCahcePlugin;

	private String jdbcType = "";

	/**
	 * TODO 简单描述该方法的实现功能（可选）.
	 *
	 * @see com.apache.api.manager.PluginConnector#execute(com.apache.api.vo.ParamsVo)
	 */
	public Object execute(ParamsVo param) throws Exception {
		String key = String.valueOf(param.getParams("sqlKeyId"));
		MethodParam params = new MethodParam(key, "", "", IusSqlTools.SPANCENAME);
		ResultEntity entity = new ResultEntity();
		entity.setResult("true");
		try {
			log.info("parameter datasource ["+param.getParamsToStr("datasource")+"]");
			String resultType = String.valueOf(param.getParams("resultType"));
			if ("processSql".equalsIgnoreCase(resultType)) {
				processSql(entity, params, param);
			} else if ("objInfo".equals(resultType)) {
				selectObjInfo(entity, params, param);
			}
			String cacheKey = param.getParamsToStr("resultSetCacheKey");//批定的缓存KEy
			if(Validator.isNotNull(cacheKey)){//是否写缓存
				iusCahcePlugin.writeCahce(param,entity);
			}
		} catch (BusinessException e) {
			e.printStackTrace();
			param.setParams("businessException", e.getMessage());
			throw new BusinessException(e.getMessage());
		}
		return entity;
	}

	private void processSql(ResultEntity entity, MethodParam params, ParamsVo paramVo) {
		String execSql = "";
		String cateNo = String.valueOf(paramVo.getParams("cateNo"));
		String auditType = String.valueOf(paramVo.getParams("auditType"));
		if (Validator.isNotNull(cateNo) || Validator.isNotNull(auditType)) {
			FelToolsUtil.getInstance().evl(paramVo);
		}
		ResultEntity rsEntity = beforeMenthod(entity, paramVo);
		if (!Validator.isEmpty(rsEntity)) {//方法前拦截是否需要直接返回
			entity = rsEntity;
			return;
		}
		execSql = IusSqlTools.getInstance().cteageNativeSql(paramVo);
		String pluginSql = String.valueOf(paramVo.getParams(CustomMethodPlugin.pluginSql));//插件中生成的sql
		if (Validator.isNotNull(pluginSql)) {
			execSql += pluginSql;
		}
		if (Validator.isNotNull(execSql)) {
			String modelTypes = String.valueOf(paramVo.getParams("modelTypes"));
			String str[] = modelTypes.split(",");
			for (int i = 0; i < str.length; i++) {
				if (str[i].startsWith("d_")) {
					String sql = String.valueOf(paramVo.getParams(str[i].substring(2) + "_sql"));
					if (StrUtil.isNotNull(sql)) {
						params.setKey("ByObjInfo");
						params.setParams("dyncSql", sql);
						List list = iusPubDao.select(params);
						if (null != list && list.size() > 0) {
							delContentInfo(list);
						}
					}
				}
			}
			params.setParams("dyncSql", "");
			params.setKey("ByDymicSql");
			params.setParams("execSql", execSql.replace("\\", "\\\\"));
			boolean mark = iusPubDao.edit(params);
			entity.setEntity(paramVo.getParams("resultIds"));
			entity.setResult("T");
			entity.setMessage("操作成功");
		} else {
			entity.setMessage("缺少方法执行参数");
		}
	}

	private void selectObjInfo(ResultEntity entity, MethodParam params, ParamsVo paramVo) {
		ResultEntity rsEntity = beforeMenthod(entity, paramVo);
		if (!Validator.isEmpty(rsEntity)) {//方法前拦截是否需要直接返回
			entity = rsEntity;
			return;
		}
		params.setParams("datasource",paramVo.getParamsToStr("datasource"));
		String execSql = IusSqlTools.getInstance().dymicNativeSql(paramVo);
		if (Validator.isNotNull(execSql)) {
			String modelTypes = String.valueOf(paramVo.getParams("modelTypes"));
			String str[] = modelTypes.split(",");
			if (modelTypes.startsWith("s_") || modelTypes.startsWith("sl_") || modelTypes.startsWith("sr_")
					|| modelTypes.startsWith("si_")) {
				params.setKey("ByObjInfo");
				params.setParams("dyncSql", execSql.replace("\\", "\\\\"));
				Object obj = null;
				params.setResultCache(false);
				String rows = String.valueOf(paramVo.getParams("rows"));
				if (Validator.isNull(rows)) {
					String val = String.valueOf(paramVo.getParams("resultObjType"));
					if ("obj".equals(val)) {
						List list = iusPubDao.select(params);
						obj = Validator.isEmpty(list) ? null : list.get(0);
						if (null == obj) {
							entity.setMessage("未获取到数据");
							return;
						}
						if (str.length == 1) {
							Map result = (Map) obj;
							String objName = "";
							if ("T".equalsIgnoreCase(String.valueOf(paramVo.getParams("_resultType")))) {
								objName = modelTypes.substring(2) + ".";
								Map nn = (Map) result.get(modelTypes.substring(2));
								if (nn.containsKey("fsId")) {
									getBulidContent("", nn);
								}
							} else {
								if (result.containsKey("fsId")) {
									obj = getBulidContent(objName, result);
								}
							}
						} else {
							for (int i = 0; i < str.length; i++) {
								String objName = str[i].substring(2) + ".";
								Map result = (Map) obj;
								if (result.containsKey(objName + "fsId")) {
									obj = getBulidContent(objName, result);
								}
							}
						}
					} else if ("count".equals(val)) {
						long count = iusPubDao.count(params);
						entity.setEntity(count);
						entity.setResult("查询成功");
						obj = count;
					} else {
						obj = iusPubDao.select(params);
					}
				} else {
					params.setPageIndex(
							Integer.valueOf(StrUtil.doNull(String.valueOf(paramVo.getParams("page")), "1")));
					params.setPageSize(Integer.valueOf(rows));
					obj = iusPubDao.pageSelect(params);
				}
				if (!Validator.isEmpty(obj)) {
					entity.setEntity(obj);
					entity.setResult("查询成功");
				} else {
					entity.setMessage("执行失败");
				}
			} else {
				for (int i = 0; i < str.length; i++) {
					if (str[i].startsWith("d_")) {
						String sql = String.valueOf(paramVo.getParams(str[i].substring(2) + "_sql"));
						if (StrUtil.isNotNull(sql)) {
							params.setKey("ByObjInfo");
							params.setParams("dyncSql", sql);
							List list = iusPubDao.select(params);
							if (null != list && list.size() > 0) {
								delContentInfo(list);
							}
						}
					}
				}
				params.setParams("dyncSql", "");
				params.setKey("ByDymicSql");
				params.setParams("execSql", execSql);
				boolean resMark = iusPubDao.edit(params);
				entity.setEntity(null == paramVo.getParams("resultIds") ? resMark : paramVo.getParams("resultIds"));
				entity.setResult("T");
			}
		} else {
			entity.setMessage("缺少方法执行参数");
		}
	}

	private ResultEntity beforeMenthod(ResultEntity entity, ParamsVo paramVo) {
		exeCustomPlugin(paramVo, "befor");
		if (Validator.isNotNull(String.valueOf(paramVo.getParams(CustomMethodPlugin.resultMark)))) {
			entity.setResult("T");
			entity.setMessage(String.valueOf(paramVo.getParams(CustomMethodPlugin.resultMark)));
			if (!Validator.isEmpty(paramVo.getParams(CustomMethodPlugin.pluginInnerReturn))) {
				entity.setEntity(paramVo.getParams(CustomMethodPlugin.pluginInnerReturn));
			}
			return entity;
		}
		return null;
	}

	private Object getBulidContent(String objName, Map result) {
		String key = String.valueOf(result.get(objName + "fsId"));
		if (StrUtil.isNull(key))
			return "";
		MaxContentPorxyPlugin plugin = MaxContentPorxyPluginImpl.getInstance();
		String dbType = "";
		if (!key.startsWith("cache_"))
			dbType = "file";
		String content = String.valueOf(plugin.doContent(key, dbType));
		if (StrUtil.isNotNull(content)) {
			JSONObject jb = JSONObject.fromObject(content);
			Map<String, Object> map = (Map<String, Object>) jb;
			for (String k : map.keySet()) {
				if (!result.containsKey(objName + k)) {
					result.put(objName + k, map.get(k));
				}
			}
		}
		return result;
	}

	private void delContentInfo(List list) {
		MaxContentPorxyPlugin plugin = MaxContentPorxyPluginImpl.getInstance();
		for (int i = 0; i < list.size(); i++) {
			Map<String, String> map = (Map) list.get(i);
			String key = map.get("fsId");
			if (StrUtil.isNull(key))
				continue;
			String dbType = "";
			if (!key.startsWith("cache_"))
				dbType = "file";
			plugin.delContent(key, dbType);
		}
	}

	private void exeCustomPlugin(ParamsVo vo, String type) {
		Map<String, Object> map = new HashMap<String, Object>();
		String keys = String.valueOf(vo.getParams("sqlKeyId"));
		if (Validator.isNotNull(keys)) {
			String beforMethodKey = String.valueOf(vo.getParams("beforMethodKey"));
			if (Validator.isNull(beforMethodKey)) {
				return;
			}
			vo.setMethodKey("beforMethodKey");
			map = (Map) getPlugin().doInvoke(vo);
			vo.setParams("beforMethodKey", "");
			vo.setParams("sqlKeyId", "");
		} else {
			if ("befor".equals(type)) {
				String beforMethodKey = String.valueOf(vo.getParams("beforMethodKey"));
				if (Validator.isNull(beforMethodKey))
					return;
				vo.setMethodKey("beforMethodKey");
				CustomMethodPlugin befor = CustomMethodFactory.getInstance().getPluginByKey(beforMethodKey);
				if (!Validator.isEmpty(befor)) {
					map = (Map) befor.beforeInvoke(vo.getParams());
					vo.setParams("beforMethodKey", "");
				}
			}
		}
		if (!Validator.isEmpty(map)) {
			for (String key : map.keySet()) {
				vo.setParams(key, map.get(key));
			}
		}
	}

	public void setIusPubDao(IDao iusPubDao) {
		this.iusPubDao = iusPubDao;
	}

	private IusSqlPorxyPlugin getPlugin() {
		if (null == iusSqlPorxyPlugin) {
			iusSqlPorxyPlugin = (IusSqlPorxyPlugin) SpringContextLoader.getBean("iusSqlPorxyPlugin");
		}
		return iusSqlPorxyPlugin;
	}

	//	public void setNetSqlPorxyPlugin(NetSqlPorxyPlugin netSqlPorxyPlugin) {
	//		this.netSqlPorxyPlugin = netSqlPorxyPlugin;
	//	}

}
